-----------------------------------------------------------------------
-- File:        Crossing.adb
-- Description: Provides crossing acquiring and release functionality
--
-- Requires:    Io_Ports,Unsigned_Types,Raildefs,Dio192defs, Dda06defs,
--              Int32defs,Dio192_Blocks
--				
-- Author:     Ha Le
-----------------------------------------------------------------------

with Ada.Text_IO; --*
with Io_Ports;
with Unsigned_Types;
use Unsigned_Types;  -- 1.8
with Raildefs,
   Dio192defs, Dda06defs, Int32defs;
use Raildefs;
with Dio192_Blocks;

package body Crossing is --PROTECTED

   --Declaration of types
   type Crossing_State is array (Raildefs.Crossing_Idx range 1 .. 5) of Boolean;
   type Crossing_Owner is array (Raildefs.Crossing_Idx range 1 .. 5) of Train_Idx;
   type Crossing_MaxTime is array (Raildefs.Crossing_Idx range 1 .. 5) of Natural;
   Max_Time : constant Natural := 30;

   --Protected Object Declaration
   protected Object is
      --Protected procedures declaration
      --Acquire a crossing
      procedure Acquire_Crossing (
            Success :    out Boolean;
            Train   : in     Raildefs. Train_Id;
            C       : in     Raildefs. Crossing_Idx);
      --Release a crossing
      procedure Release_Crossing (
            Train : in     Raildefs. Train_Id;
            C     : in     Raildefs. Crossing_Idx);

   private
      --private variables
      Crossing_Status:Crossing_State:= (others => False);
      Owner: Crossing_Owner:= (others => 0);
      Crossing_Timeout : Crossing_MaxTime := (others => Max_Time);

   end Object;

   --Protected Object Body
   protected body Object is

      --Acquire a Crossing
      procedure Acquire_Crossing (
            Success :    out Boolean;
            Train   : in     Raildefs. Train_Id;
            C       : in     Raildefs. Crossing_Idx) is
      begin
         if Crossing_Timeout(C)= 0 or Crossing_Status(C)=False or Owner(C) =
               Train then
            Success := True;
            Crossing_Status(C):=True;
            Owner(C):=Train;
            Crossing_Timeout(C) := Max_Time;
         else
            Crossing_Timeout(C):= Crossing_Timeout(C) -1;
            Success := False;
         end if;
        null;
         Ada.Text_Io.Put_Line("Acquiring Crossing...."&C'Img&"Enquiring   "&Train'Img&"Owner..."&Owner(C)'Img&"Success "&Success'Img); --*
      end Acquire_Crossing;

      --Release a Crossing
      procedure Release_Crossing (
            Train : in     Raildefs. Train_Id;
            C     : in     Raildefs. Crossing_Idx) is
      begin
         if(Train =Owner(C)) then
            Crossing_Status(C):=False;
            Owner(C):=0;
         end if;
         Ada.Text_Io.Put_Line("Release Crossing...."&C'Img&"Owner..."&Owner(C)'Img); --*
      end Release_Crossing;

   end Object;

   --Public Procedures

   --Acquire a Crossing
   procedure Acquire_Crossing (
         Success :    out Boolean;
         Train   : in     Raildefs. Train_Id;
         B       : in     Raildefs. Crossing_Idx) is

   begin

      Object. Acquire_Crossing (Success, Train, B);

   end Acquire_Crossing;

   --Release a Crossing
   procedure Release_Crossing (
         Train : in     Raildefs. Train_Id;
         B     : in     Raildefs. Crossing_Idx) is

   begin
      Object. Release_Crossing (Train,B);
   end Release_Crossing;


end Crossing;